
#include <iostream>
#include <memory>

/* 函数参数的传递:
 * 1. 值传递，修改函数的形参对实际参数没有影响
 * 2. 指针传参，传递实参的地址给形参，通过修改实参来修改实参
 * 3. 引用传参，参数的引用复制给形参，使得形参可以修改实参
*/

/* unique_ptr采用独享语义，在任何给定时刻，只能有一个指针管理内存。当指针超出作用域时，内存将自动释放，而且该类型的指针不可copy，只可以move。
 * unique_ptr 不支持拷贝和赋值，只支持转移
 * unique_ptr 不支持拷贝构造函数和赋值重载函数，禁用掉，只能转移使用
 * 使用原始指针申请的动态内存不会在程序结束时，自动释放会造成内存泄露，unique_ptr会在程序运行周期结束时自动调用析构函数来释放掉其申请的内存，不易造成内存的泄漏
 * 
*/

using namespace std;

typedef struct ARRAY_t
{
    int data[10];
}ARRAY;


int main(int argc, char *argv[])
{
    int *pp = new int(19);
    unique_ptr<int> p1(new int(19));
    // unique_ptr<int> p1 = pp; // 不能这样定义，因为其析构阻止了隐式定义

    // unique_ptr<int> p3 = p1; // 不能这样定义，因为unique_ptr不支持拷贝赋值，只支持转移
    // unique_ptr<int> p3(p1); // 不能这样定义，因为unique_ptr不支持拷贝赋值，只支持转移


    int *p2 = p1.get();// 普通指针

    printf("value: %d  %d \n",*p1.get(),*p2);
    printf("addr: %p %p \n",p1.get(),p2);

    unique_ptr<int> p3;
    // p1.release();//释放 p1 的所有权
    p1.reset(new int(90));  // p1.reset(obj) 用来替换智能指针管理的对象，如果传入的为空，则释放托管对象资源并置空，如果传入另一指针，先释放前一指针，再托管后面的。
    p3.swap(p1);// 将p1的所有权转移给p3，p1设置为nullptr
    
    if (p1.get() == nullptr)
    {
        printf("P1 is moved!\n");
    }
    int *p4 = p3.get();// 普通指针
    
    // if (p1.)
    printf("value: %d %d \n",*p3.get(),*p4);
    printf("addr: %p %p \n",p3.get(),p4);


    // 对数组的操作，auto_ptr不能对数组操作，因为其定义为delete obj 没有 delete[] obj
    ARRAY data1;

    for (int i = 0;i < 10;i++)
    {
        data1.data[i] = i + 2;
    }
    unique_ptr<ARRAY> p6(new ARRAY(data1));

    printf("value: %d \n",p6.get()->data[8]);

    

    return 0;

}